package webServices;

import Entities.Cliente;
import Entities.Externo;
import Entities.ItemProducto;
import Entities.Mesa;
import Entities.Producto;
import Entities.Reserva;
import Entities.Usuario;
import ejb.Condicional;
import ejb.ConsultaUniversalFacadeLocal;
import ejb.ItemProductoFacadeLocal;
import ejb.PedidoFacadeLocal;
import ejb.ProductoFacadeLocal;
import ejb.ReservaFacadeLocal;
import ejb.UsuarioFacadeLocal;
import ejb.soportes.Consulta;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.List;
import javax.ejb.EJB;
import javax.jws.WebService;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@WebService(serviceName = "WebServiceSGR")
@Stateless()
public class WebServiceSGR {

    @PersistenceContext(unitName = "SGR-ejbPU")
    private EntityManager em;

    protected EntityManager getEntityManager() {
        return em;
    }
    @EJB
    private ReservaFacadeLocal ejbRes;
    @EJB
    private PedidoFacadeLocal ejbPed;
    @EJB
    private UsuarioFacadeLocal ejbUsu;
    @EJB
    private ConsultaUniversalFacadeLocal consultaUniversalFacade;
    @EJB
    private ProductoFacadeLocal ejbPro;
    @EJB
    private ItemProductoFacadeLocal ejbIP;

    @WebMethod(operationName = "reservar")
    public int reservar(@WebParam(name = "reserva") ReservaTransporteWS reservaWS,
            @WebParam(name = "nombreUsuario") String nombreUsuario,
            @WebParam(name = "contrasenia") String contrasenia) {
        Cliente cliente;
        Usuario usuario;
        Reserva reservaEntidad = new Reserva();
        try {
            if (reservaWS != null && reservaWS.getCantidad() > 0
                    && reservaWS.getFechaHora() > 0 && reservaWS.getHorario() > 0) {
                usuario = this.comprobarUsuario(nombreUsuario, contrasenia);
                reservaEntidad.setCantidad(reservaWS.getCantidad());
                Calendar cl = Calendar.getInstance();
                cl.setTime(new Date(reservaWS.getFechaHora()));
                reservaEntidad.setFechaHora(cl);
                reservaEntidad.setComentario(reservaWS.getComentario());
                reservaEntidad.setHorario(reservaWS.getHorario());
                if (usuario != null) {
                    if (usuario instanceof Cliente) {
                        cliente = (Cliente) usuario;
                        reservaEntidad.setCliente(cliente);
                        int anio_ = reservaEntidad.getFechaHora().get(Calendar.YEAR);
                        int mes_ = reservaEntidad.getFechaHora().get(Calendar.MONTH) + 1;
                        int dia_ = reservaEntidad.getFechaHora().get(Calendar.DAY_OF_MONTH);
                        Calendar calF = Calendar.getInstance();
                        calF.set(anio_, (mes_ - 1), dia_, 0, 0, 0);
                        reservaEntidad.setFechaHora(calF);
                        String fecha = anio_ + "-" + mes_ + "-" + dia_;
                        try {
                            Query query = em.createNativeQuery("Select m.id from mesa m where m.ACTIVO = true and "
                                    + "m.MAXIMO >= " + reservaEntidad.getCantidad() + " and m.MINIMO <= " + reservaEntidad.getCantidad()
                                    + " and m.id not in (Select rm.listaMesas_id from reserva_mesa rm INNER JOIN "
                                    + "reserva r on rm.Reserva_ID = r.ID and r.FECHAHORA = '" + fecha
                                    + "' and r.HORARIO = " + reservaEntidad.getHorario() + ") limit 1");
                            int idMesa = (int) query.getSingleResult();
                            if (idMesa != 0) {
                                Query q = em.createQuery("Select m from Mesa m where m.id = " + idMesa);
                                Mesa m = (Mesa) q.getSingleResult();
                                List<Mesa> lm = new ArrayList();
                                lm.add(m);
                                reservaEntidad.setListaMesas(lm);
                                reservaEntidad.setActivo(true);
                                if (ejbRes.reservar(reservaEntidad)) {
                                    return Mensajes.OK_RESERVAR;
                                } else {
                                    return Mensajes.ERROR_RESERVAR;
                                }
                            } else {
                                return Mensajes.ERROR_LLAMAR_MESA;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            return Mensajes.ERROR_LLAMAR_MESA;
                        }
                    } else {
                        return Mensajes.ERROR_EMPLEADO;
                    }
                } else {
                    return Mensajes.ERROR_PASS_USUARIO;
                }
            } else {
                return Mensajes.ERROR_DATOS_INCOMPLETOS;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Mensajes.ERROR_FATAL;
        }
    }

    @WebMethod(operationName = "crearPedidoExterno")
    public int crearPedidoExterno(@WebParam(name = "pedidoExterno") PedidoExternoTransporteWS externoWS,
            @WebParam(name = "nombreUsuario") String nombreUsuario,
            @WebParam(name = "contrasenia") String contrasenia) {
        Cliente cliente;
        Usuario usuario;
        Externo externo = new Externo();
        try {
            if (externoWS != null && !externoWS.getDireccion().equals("") && !externoWS.getProductos().equals("")) {
                usuario = this.comprobarUsuario(nombreUsuario, contrasenia);
                if (usuario != null) {
                    if (usuario instanceof Cliente) {
                        externo.setDireccion(externoWS.getDireccion());
                        List<ItemProducto> listaItemsProductos = new ArrayList();
                        String[] array = externoWS.getProductos().split(";");
                        int[] productosArray = new int[array.length];
                        for (int i = 0; i < array.length; i++) {
                            productosArray[i] = Integer.parseInt(array[i]);
                        }
                        for (int i = 0; i < productosArray.length; i++) {
                            if (listaItemsProductos.isEmpty()) {
                                Producto p = ejbPro.buscarPorId(productosArray[i]);
                                ItemProducto ip = new ItemProducto(0, p, p.getPrecio());
                                listaItemsProductos.add(ip);
                            } else {
                                boolean agregar = true;
                                for (Iterator<ItemProducto> it = listaItemsProductos.iterator(); it.hasNext();) {
                                    ItemProducto itemProducto = it.next();
                                    if (productosArray[i] == itemProducto.getProducto().getId()) {
                                        agregar = false;
                                        break;
                                    }
                                }
                                if (agregar) {
                                    Producto p = ejbPro.buscarPorId(productosArray[i]);
                                    ItemProducto ip = new ItemProducto(0, p, p.getPrecio());
                                    listaItemsProductos.add(ip);
                                }
                            }
                            for (ItemProducto itemProd : listaItemsProductos) {
                                if (productosArray[i] == itemProd.getProducto().getId()) {
                                    int cantidad = itemProd.getCantidad() + 1;
                                    itemProd.setCantidad(cantidad);
                                }
                            }
                        }
                        if (listaItemsProductos.size() > 0) {
                            externo.setListaItemsProductos(listaItemsProductos);
                        } else {
                            return Mensajes.ERROR_FATAL;
                        }
                        externo.setActivo(true);
                        externo.setFacturado(false);
                        Calendar fecha = new GregorianCalendar();
                        externo.setFechaHora(fecha.getTime());
                        Calendar fechaEnvio = new GregorianCalendar();
                        fechaEnvio.add(Calendar.MINUTE, 30);
                        externo.setFechaHoraEnvio(fechaEnvio.getTime());
                        cliente = (Cliente) usuario;
                        externo.setCliente(cliente);
                        ejbPed.crear(externo);
                        return Mensajes.OK_PEDIDO_EXTERNO;
                    } else {
                        return Mensajes.ERROR_EMPLEADO;
                    }
                } else {
                    return Mensajes.ERROR_PASS_USUARIO;
                }
            } else {
                return Mensajes.ERROR_DATOS_INCOMPLETOS;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Mensajes.ERROR_FATAL;
        }
    }

    @WebMethod(operationName = "horario")
    public int horario() {
        Calendar cal = Calendar.getInstance();
        int hora = cal.get(Calendar.HOUR_OF_DAY);
        if (hora < 12) {
            return 1;
        }
        if (hora < 14) {
            return 2;
        }
        if (hora < 19) {
            return 3;
        }
        if (hora <= 24) {
            return 4;
        }
        return 0;
    }

    @WebMethod(operationName = "listaProductos")
    public int[] listaProductos() {
        int[] listaProd;
        List<Producto> listaProductos = new ArrayList<>();
        try {
            Producto producto = new Producto();
            producto.setActivo(true);
            listaProductos = consultaUniversalFacade.consultar(new Consulta(producto));
            if (listaProductos.size() > 0) {
                listaProd = new int[listaProductos.size()];
                int i = 0;
                for (Producto prod : listaProductos) {
                    listaProd[i] = prod.getId();
                    i++;
                }
                return listaProd;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @WebMethod(operationName = "login")
    public int login(@WebParam(name = "nombreUsuario") String nombreUsuario,
            @WebParam(name = "contrasenia") String contrasenia) {
        Usuario usuario;
        try {
            usuario = this.comprobarUsuario(nombreUsuario, contrasenia);
            if (usuario != null) {
                if (usuario instanceof Cliente) {
                    return Mensajes.OK_PASS_USUARIO;
                } else {
                    return Mensajes.ERROR_EMPLEADO;
                }
            } else {
                return Mensajes.ERROR_PASS_USUARIO;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Mensajes.ERROR_FATAL;
        }
    }

    @WebMethod(operationName = "devolverProducto")
    public ProductoTransporteWS devolverProducto(@WebParam(name = "id") int id) {
        ProductoTransporteWS productoWS = new ProductoTransporteWS();
        List<Producto> listaProducto = new ArrayList<>();
        try {
            Producto producto = new Producto();
            producto.setActivo(true);
            producto.setId(id);
            listaProducto = consultaUniversalFacade.consultar(new Consulta(producto));
            if (listaProducto.size() > 0) {
                producto = listaProducto.get(0);
                productoWS.setId(producto.getId());
                productoWS.setDescripcionCorta(producto.getDescripcionCorta());
                productoWS.setDescripcionLarga(producto.getDescripcionLarga());
                productoWS.setIdCategoria(producto.getIdCategoria());
                productoWS.setPrecio(producto.getPrecio());
                if (producto.getFechaUltimaMod() != null) {
                    productoWS.setFechaUltimaMod(producto.getFechaUltimaMod().getTimeInMillis());
                }
                productoWS.setActivo(producto.isActivo());
                return productoWS;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    @WebMethod(operationName = "devolverDireccionCliente")
    public String devolverDireccionCliente(@WebParam(name = "nombreUsuario") String nombreUsuario,
            @WebParam(name = "contrasenia") String contrasenia) {
        Usuario usuario;
        try {
            usuario = this.comprobarUsuario(nombreUsuario, contrasenia);
            if (usuario != null) {
                if (!usuario.getDetalle().trim().equals("")) {
                    return (usuario.getCalle() + " " + usuario.getNumero() + ", " + usuario.getDetalle());
                } else {
                    return (usuario.getCalle() + " " + usuario.getNumero());
                }
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private String toHexadecimal(byte[] digest) {
        String hash = "";
        for (byte aux : digest) {
            int b = aux & 0xff;
            if (Integer.toHexString(b).length() == 1) {
                hash += "0";
            }
            hash += Integer.toHexString(b);
        }
        return hash;
    }

    private String codificarPassword(String cadena) {
        byte[] digest = null;
        byte[] buffer = cadena.getBytes();
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            messageDigest.update(buffer);
            digest = messageDigest.digest();
        } catch (NoSuchAlgorithmException ex) {
        }
        return toHexadecimal(digest);
    }

    private Usuario comprobarUsuario(String nombreUsuario, String contrasenia) {
        Condicional cond1 = new Condicional("nombreUsuario", nombreUsuario, "=");
        Condicional cond2 = new Condicional("contrasenia", codificarPassword(contrasenia), "=");
        Condicional cond3 = new Condicional("activo", true, "=");
        List<Condicional> parametros = new ArrayList<>();
        parametros.add(cond1);
        parametros.add(cond2);
        parametros.add(cond3);
        try {
            List<Usuario> lista = ejbUsu.buscarConParametros(parametros, null, new int[]{0, 1});
            if (lista.size() > 0) {
                return (Usuario) lista.get(0);
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
